#region Imports
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using System.Text;

using BO = PHSRAG.Insight21.BusinessObjects;
using DataAccess = PHSRAG.Utility.DataAccess;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using PHSRAG.Insight21.FormsManagement;
#endregion

namespace PHSRAG.Insight21.CDS
{
	/// <summary>
	/// Represents a person 
	/// </summary>
	public class Person : BO.SmartBusinessObject
	{
		/// <summary>
		/// Type of Person (internal or external)
		/// </summary>
		public enum PersonType
		{
			Internal = 1,
			External
		}

		#region Constants
		private const string PersonKey = "personkey_B084814C-E130-4358-A477-FEED9B21A8A8";
		private const string PersonTableName = "Person";
		#endregion

		#region Private Instance Variables
		private string lastName;
		private string firstName;
		private string middleName;
		private string dept;
		private string title;
		private string phoneArea;
		private string phoneNumber;
		private string faxArea;
		private string faxNumber;
		private string email;
		private string username;
		private string orgName;
		private int orgId;
		private int admPersonType;
		private int degreeId;
		private int rexRecomId;
		
		private bool citiDataDetermined;
		private bool isCitiCertified;
		private string citiCertDate;

		private bool occHealthDataDetermined;
		private bool isOccHealthCertified;
		private string occHealthCertDate;

		private bool hasSpeciesExperience;
		private string speciesExperienceDate;
		private string speciesType;

		private int userId;

		private Certifications certifications;
		private Address address;
		private ArrayList degrees;
		#endregion

		#region Public Properties
        /// <summary>
        /// Gets the full name of the Person
        /// </summary>
        public string FullName
        {
            get { return string.Format("{0}, {1}", LastName, FirstName); }
        }

		/// <summary>
		/// Gets/Sets the Last Name of the Person
		/// </summary>
		public string LastName
		{
			get { return lastName; }
			set { SetDirty(ref lastName, value); }
		}

		/// <summary>
		/// Gets/Sets the First Name of the Person
		/// </summary>
		public string FirstName
		{
			get { return firstName; }
			set { SetDirty(ref firstName, value); }
		}

		/// <summary>
		/// Gets/Sets the Middle Name of the Person
		/// </summary>
		public string MiddleName
		{
			get { return middleName; }
			set { SetDirty(ref middleName, value); }
		}

		/// <summary>
		/// Gets/Sets the Username of the Person if it exists, otherwise returns 
		/// an empty string
		/// </summary>
		public string Username
		{
			get { return username; }
			set { SetDirty(ref username, value); }
		}

		/// <summary>
		/// Gets/Sets the Id of the person's degree
		public int DegreeId
		{
			get { return degreeId; }
			set { SetDirty(ref degreeId, value); }
		}

		/// <summary>
		/// Gets/Sets person's primary org id/Returns the id of the Person's primary organization if it exists,
		/// otherwise returns 0
		/// </summary>
		public int OrganizationId
		{
			get { return orgId; }
			set { SetDirty(ref orgId, value); }
		}

		/// <summary>
		/// Gets/Sets person's primary org name/Returns the name of the Person's primary organization if it exists,
		/// otherwise returns an empty string
		/// </summary>
		public string OrganizationName
		{
			get { return orgName; }
			set { SetDirty(ref orgName, value); }
		}

		/// <summary>
		/// Get/Set the department the person works under
		/// </summary>
		public string Department
		{
			get { return dept; }
			set { SetDirty(ref dept, value); }
		}

		/// <summary>
		/// Get/Set the person's job title
		/// </summary>
		public string Title
		{
			get { return title; }
			set { SetDirty(ref title, value); }
		}

		/// <summary>
		/// Get/Set the area code of the person's primary phone number
		/// </summary>
		public string PhoneArea
		{
			get { return phoneArea; }
			set { SetDirty(ref phoneArea, value); }
		}

		/// <summary>
		/// Get/Set the non area code portion of the person's primary phone number
		/// </summary>
		public string PhoneNumber
		{
			get { return phoneNumber; }
			set { SetDirty(ref phoneNumber, value); }
		}

		/// <summary>
		/// Get/Set the area code of the person's fax number
		/// </summary>
		public string FaxArea
		{
			get { return faxArea; }
			set { SetDirty(ref faxArea, value); }
		}

		/// <summary>
		/// Get/Set the non area code portion of the person's fax number
		/// </summary>
		public string FaxNumber
		{
			get { return faxNumber; }
			set { SetDirty(ref faxNumber, value); }
		}

		/// <summary>
		/// Get/Set the person's primary email address
		/// </summary>
		public string Email
		{
			get { return email; }
			set { SetDirty(ref email, value); }
		}

		/// <summary>
		/// Get/Set the type of the person (internal or external)
		/// </summary>
		public int AdmPersonType
		{
			get { return admPersonType; }
			set { SetDirty(ref admPersonType, value); }
		}

		/// <summary>
		/// Some people may have Rex Recom IDs that 
		/// correspond to their records in the Rex tblRecomAbstract.
		/// This is that ID, in case we're moving people over to Rex.
		/// </summary>
		public int RexRecomId
		{
			get { return rexRecomId; }
			set { SetDirty(ref rexRecomId, value); }
		}

		/// <summary>
		/// Gets the person's address
		/// </summary>
		public Address Address
		{
			get { return address; }
		}

		/// <summary>
		/// Certifications the person has for training
		/// </summary>
		public Certifications Certifications
		{
			get
			{
				if (certifications == null)
				{
					certifications = new Certifications(CachePolicy);
					certifications.Load(DataAccess.GetConnectionString(), Id);
				}
				return certifications;
			}
		}

		/// <summary>
		/// Gets if the person has passed CITI training. Here's the business rule:
		/// If the (Type is IRB) OR (the type is  IRB Continuing Education and Subtype = CITI CE) 
		/// AND Status = Pass AND Certification Date less than 2 years ago then the person is CITI Certified. 
		/// Otherwise they are NOT certified (i.e. their certification is expired), so return no.
		/// </summary>
		public bool IsCitiCertified
		{
			get
			{
				if (!citiDataDetermined)
					DetermineCitiData();
				return isCitiCertified;
			}
		}

		/// <summary>
		/// Gets the date the person passed CITI certification.  If the person has ever been CITI certified,
		/// This is the date of their valid certification OR the date of their expired certification if the 
		/// certification is not currently valid.  If the person has never passed CITI certification, the string
		/// is empty.
		/// </summary>
		public string CitiCertDate
		{
			get
			{
				if (!citiDataDetermined)
					DetermineCitiData();
				return citiCertDate;
			}
		}

		/// <summary>
		/// Gets if the person has passed Occ Health training. Here's the business rule:
		/// If the (the type is  IACUC Continuing Education and Subtype = Occupational health program) 
		/// AND Status = Pass AND Certification Date less than 3 years ago then the person is Occ Health Certified. 
		/// Otherwise they are NOT certified (i.e. their certification is expired), so return no.
		/// </summary>
		public bool IsOccHealthCertified
		{
			get 
			{
				if (!occHealthDataDetermined)
					DetermineOccHealthData();
				return isOccHealthCertified;
			}
		}

		/// <summary>
		/// Gets the date the person passed Occ Health certification.  If the person has ever been Occ Health certified,
		/// this is the date of their valid certification OR the date of their expired certification if the 
		/// certification is not currently valid.  If the person has never passed Occ Health certification, the string
		/// is empty.
		/// </summary>
		public string OccHealthCertDate
		{
			get
			{
				if (!occHealthDataDetermined)
					DetermineOccHealthData();
				return occHealthCertDate;
			}
		}

		/// <summary>
		/// Person's FwkDomainUserId which is the Insight login id.  If the Person
		/// does not have a login, the UserId is zero.
		/// </summary>
		public int UserId
		{
			get
			{
				return userId;
			}
		}

		/// <summary>
		/// Gets a list of degrees a person holds
		/// </summary>
		public ArrayList Degrees
		{
			get
			{
				if (degrees == null)
					degrees = Degree.GetDegrees(Id, CachePolicy);
				return degrees;
			}
		}

		/// <summary>
		/// A comma concatenated string of Degrees
		/// </summary>
		public string DegreeList
		{
			get
			{
				StringBuilder degreeList = new StringBuilder();
				foreach (Degree degree in Degrees)
				{
					degreeList.Append(string.Format("{0}, ", degree.Name));
				}
				//if there is atleast 1 degree, then remove the extra ", " towards the end of the string
				if (degreeList.Length > 1)
					degreeList.Remove(degreeList.Length - 2, 2); //, and space towards the end of degreeList appended in the foreach loop above
				return degreeList.ToString();
			}
		}
		#endregion

		#region Constructors
		/// <summary>
		/// Initializes the base with the specified cache policy 
		/// </summary>
		/// <param name="cachePolicy">policy to use to cache the instance</param>
		public Person(ICachePolicy cachePolicy)
			: base(cachePolicy)
		{
			address = new Address(cachePolicy);
		}
		#endregion

		#region Overridden methods
        /// <summary>
        /// Determine if this is equal to another object based on Id.  Useful
        /// when seeing if an arraylist already contains a person
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            Person person = obj as Person;
            if (person == null) return false;

            return (this.Id == person.Id);
        }

        /// <summary>
        /// Return a unique hashcode for this person
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return Id;
        }

        /// <summary>
		/// Determines whether this instance has data that has changed on the object that has
		/// not been persisted in the database
		/// </summary>
		/// <returns>whether the object is dirty</returns>
		public override bool IsDirty()
		{
			return (Address.IsDirty() || Dirty);
		}

		/// <summary>
		/// Saves the Person object's data to the data repository and sets the state back to non-dirty
		/// </summary>
		/// <param name="sqlConnection">Sql Connection object</param>
		protected override void SaveObject(SqlTransaction transaction)
		{
			try
			{
				Id = (int)DataAccess.ExecuteScalar(
					transaction.Connection,
					transaction,
					"UpdatePerson",
					DataAccess.BuildSqlParameterArray(
					"@admPersonId", SqlDbType.Int, Id,
					"@lastName", SqlDbType.VarChar, lastName,
					"@firstName", SqlDbType.VarChar, firstName,
					"@admPersonType", SqlDbType.Int, admPersonType,
					"@orgId", SqlDbType.Int, orgId,
					"@orgName", SqlDbType.VarChar, orgName,
                    "@areaCode", SqlDbType.VarChar, GetDBValue(phoneArea),
                    "@number", SqlDbType.VarChar, GetDBValue(phoneNumber),
                    "@email", SqlDbType.VarChar, GetDBValue(email),
                    "@middleName", SqlDbType.VarChar, GetDBValue(middleName),
					"@admDegreeId", SqlDbType.Int, (degreeId == 0) ? (object)DBNull.Value : (object)degreeId,
                    "@dept", SqlDbType.VarChar, GetDBValue(dept),
                    "@title", SqlDbType.VarChar, GetDBValue(title),
                    "@faxAreaCode", SqlDbType.VarChar, GetDBValue(faxArea),
                    "@faxNumber", SqlDbType.VarChar, GetDBValue(faxNumber)));

				address.AdmPersonId = Id;
				address.Save(transaction);

				dirty = false;
			}
			catch (Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog(
					"Save of Person failed", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Save of Person failed", e);
			}
		}

		/// <summary>
		/// Delete the Person object. DeleteObject is not currently implemented, 
		/// and will throw an exception if called. 
		/// </summary>
		/// <param name="sqlTransaction">transaction to use if were able to delete.</param>
		protected override void DeleteObject(SqlTransaction sqlTransaction)
		{
			throw new Exception("Person.DeleteObject is not supported");
		}

		/// <summary>
		/// Load the current instance with person data
		/// </summary>
		/// <param name="connectionString">contains info to connect to the data source</param>
		/// <param name="args">arguments for the stored procedure</param>
		public override void Load(string connectionString, params object[] args)
		{
			if (args.Length != 1)
				throw new Exception("Person load requires an AdmPersonId");

			try
			{
				PopulateDataMembers(DataAccess.GetDataSet(
					connectionString,
					"GetPerson",
					DataAccess.BuildSqlParameterArray("@admPersonId", SqlDbType.Int, args[0])).Tables[0].Rows[0]);

				// set id to the one passed in and used to load the instance
				Id = (int)args[0];

				// object will have been marked dirty if any of the loaded values are different
				// than the defaults
				Dirty = false;
			}
			catch (Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog(
					"Person load failed", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Person load failed", e);
			}
		}

		/// <summary>
		/// Cache Key uniquely identifies this object within the cache.
		/// </summary>
		/// <returns>the unique string for this object.</returns>
		public override string CacheKey()
		{
			return PersonKey;
		}

		/// <summary>
		/// Cache this instance using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(PersonKey, this);
		}

		/// <summary>
		/// Remove this instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(PersonKey);
		}
		#endregion

		#region Static Methods
		/// <summary>
		/// Returns the valid list of degrees
		/// </summary>
		/// <param name="connectionString">string containing info to connect to the database</param>
		/// <returns>a dataTable of Name/Id pairs</returns>
		public static DataTable GetDegreeTypes(string connectionString)
		{
			return DataAccess.GetDataSet(connectionString, "GetDegreeTypes").Tables[0];
		}

		/// <summary>
		/// Returns a Person object given a FwkDomainUserId
		/// </summary>
		/// <param name="userId">A FwkDomainUserId</param>
		/// <returns></returns>
		public static Person GetPersonByUserId(string connectionString, ICachePolicy cachePolicy, int userId)
		{
			try
			{
				Person person = new Person(cachePolicy);
				DataRow personRow = DataAccess.GetDataSet(
					connectionString,
					"GetPersonByUserId",
					DataAccess.BuildSqlParameterArray("@userId", SqlDbType.Int, userId)).Tables[0].Rows[0];
				person.PopulateDataMembers(personRow);

				// PopulateDataMembers doesn't set Id, GetPersonByUserId returns it though
				person.Id = (int)personRow["Id"];

				// object will have been marked dirty if any of the loaded values are different
				// than the defaults
				person.Dirty = false;
				return person;
			}
			catch (Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog(
					"Person load failed", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Get Person by userid failed", e);
			}
		}
		#endregion

		#region Public methods
		/// <summary>
		/// This method is called when inserting a protocol and/or staff into Rex upon Submission.
		/// If the person doesn't have a Rex ID, this method will be called, and a record inserted into Rex.
		/// It also inserts a Recom Mapping ID in the AdmPerson_RecomAbstract_Map table.
		/// </summary>
		/// <param name="rexConnectionString">the connection string to the Rex database</param>
		public void CreateRecomRecord(string insightConnectionString, string rexConnectionString)
		{
			SqlConnection rexConn = new SqlConnection(rexConnectionString);
			rexConn.Open();
			SqlTransaction rexTrans = rexConn.BeginTransaction();

			SqlConnection insightConn = new SqlConnection(insightConnectionString);
			insightConn.Open();
			SqlTransaction insightTrans = insightConn.BeginTransaction();

			try
			{
				// external users won't have a username
				object username =
					(Username == null) ? (object)DBNull.Value : (object)Username;

				// insert the user into Rex.
				RexRecomId = Convert.ToInt32(Utility.DataAccess.ExecuteScalar(rexConn, rexTrans,
						"spRECOMUpdate",
						Utility.DataAccess.BuildSqlParameterArray(
							"@nRECOMAbstractID", SqlDbType.Int, RexRecomId,
							"@sLastName", SqlDbType.VarChar, LastName,
							"@sFirstName", SqlDbType.VarChar, FirstName,
							"@sMiddleName", SqlDbType.VarChar, MiddleName,
							"@sDegrees", SqlDbType.VarChar, string.Empty,
							"@sTitleAcademic", SqlDbType.VarChar, string.Empty,
							"@sUserName", SqlDbType.VarChar, username,
							"@sGender", SqlDbType.VarChar, string.Empty,
							"@bWantsNewsletter", SqlDbType.Bit, 0,
							"@bStatus", SqlDbType.Bit, 1, // active
							"@dtDeparture", SqlDbType.DateTime, DBNull.Value,
							"@bUSCitizenship", SqlDbType.Bit, 1,
							"@sCitizenCountryCode", SqlDbType.VarChar, DBNull.Value,
							"@dtParticipationRequested", SqlDbType.DateTime, DBNull.Value,
							"@dtParticipationSigned", SqlDbType.DateTime, DBNull.Value,
							"@bPeopleFlag", SqlDbType.Bit, 1,
							"@nUserType", SqlDbType.Int, (int)AdmPersonType
						)));


				// now add the mapping record in Insight / CDS.
				Utility.DataAccess.ExecuteNonQuery(insightConn, insightTrans,
						"CreatePersonRecomMap",
						Utility.DataAccess.BuildSqlParameterArray(
							"@admPersonId", SqlDbType.Int, Id,
							"@nRecomAbstractId", SqlDbType.Int, RexRecomId,
							"@userName", SqlDbType.VarChar, username));


				rexTrans.Commit();
				insightTrans.Commit();
			}
			catch
			{
				rexTrans.Rollback();
				insightTrans.Rollback();
				throw;
			}
			finally
			{
				if (rexConn.State != ConnectionState.Closed)
					rexConn.Close();
				if (insightConn.State != ConnectionState.Closed)
					insightConn.Close();

			}

		}

		/// <summary>
		/// Gets if the person has passed Experience/training for the specified species. Here's the business rule:
		/// If the (the type is  IACUC and Subtype = Dogs experience (for ex)) 
		/// AND Status = Pass AND Certification Date less than 3 years ago then the person has experience with the species. 
		/// Otherwise not.
		/// </summary>
		/// <param name="speciesType">Type of the species</param>
		/// <returns></returns>
		public bool HasSpeciesExperience(string speciesType)
		{
			this.speciesType = speciesType;
			// using an order by to make sure we get the most recent certification date
			DataRow[] speciesExperienceData = (Certifications.GetDataContainer().Tables[0].Select(
				string.Format(@"(Type = 'IACUC' and Subtype = '{0} Experience' and Status = 'Pass')", speciesType), 
				"Date DESC"));

			if (speciesExperienceData.Length > 0)
			{
				DateTime certDate = (DateTime)speciesExperienceData[0]["Date"];
				if (certDate == DateTime.MinValue)
					hasSpeciesExperience = false;
				else
				{
					hasSpeciesExperience = (certDate > DateTime.Now.AddYears(-3));
					speciesExperienceDate = certDate.ToString("MM/dd/yyyy");
				}
			}
			else
				hasSpeciesExperience = false;

			return hasSpeciesExperience;

		}

		/// <summary>
		/// Experience Date for the specified species
		/// </summary>
		/// <param name="speciesType">Type of the species</param>
		/// <returns></returns>
		public string SpeciesExperienceDate(string speciesType)
		{
			if (this.speciesType != speciesType)
				HasSpeciesExperience(speciesType);
			return speciesExperienceDate;
		}

		public QuestionnaireAnswer GetCertificationQuestionnaireAnswer(string insightConnectionString, string questionnaireAnswerName)
		{
				DataTable dt = Utility.DataAccess.GetDataTable(insightConnectionString, "GetCertificationQuestionnaireAnswer",
						Utility.DataAccess.BuildSqlParameterArray(
						"@admPersonId", SqlDbType.Int, Id
						, "@questionnaireAnswerName", SqlDbType.VarChar, questionnaireAnswerName
						));

				if (dt.Rows.Count > 0)
				{
					return new QuestionnaireAnswer(CachePolicy, dt.Rows[0]);
				}
				else
					return null;
		}

		public void SaveCertification(string insightConnectionString, string rexConnectionString, QuestionnaireAnswer questionnaireAnswer,
			string type, string subType, string activityType, string status, string notes)
		{
            SqlConnection rexConn = new SqlConnection(rexConnectionString);
            rexConn.Open();

            SqlConnection insightConn = new SqlConnection(insightConnectionString);
            insightConn.Open();

            SqlTransaction rexTrans = rexConn.BeginTransaction();
            SqlTransaction insightTrans = insightConn.BeginTransaction();

            try
            {
                int questAnswerIdBeforeSave = questionnaireAnswer.Id;
                questionnaireAnswer.UpdateModifiedDate = true;
                questionnaireAnswer.Save(insightTrans);
                if (questAnswerIdBeforeSave == 0)
                {
                    Utility.DataAccess.ExecuteScalar(insightTrans.Connection, insightTrans, "SaveAdmPersonQuestionnaireAnswerMap",
                        Utility.DataAccess.BuildSqlParameterArray(
                        "@admPersonId", SqlDbType.Int, Id,
                        "@questionnaireAnswerId", SqlDbType.Int, questionnaireAnswer.Id
                        ));


                    /// if this fails to execute it should not update Rex and event is raised on the calling page.                    
                    // insert the training into Rex.
                    Utility.DataAccess.ExecuteNonQuery(rexConn, rexTrans,
                        "spRecomTrainingUpdate",
                        Utility.DataAccess.BuildSqlParameterArray(
                            "@nRECOMAbstractID", SqlDbType.Int, RexRecomId,
                            "@nRecomTrainingId", SqlDbType.Int, 0,
                            "@sType", SqlDbType.VarChar, type,
                            "@sSubtype", SqlDbType.VarChar, subType,
                            "@sActivityType", SqlDbType.VarChar, activityType,
                            "@sStatus", SqlDbType.VarChar, status,
                            "@dtStatus", SqlDbType.VarChar, DateTime.Now.ToShortDateString(),
                            "@sNotes", SqlDbType.VarChar, notes
                        ));
                }

                insightTrans.Commit();
                rexTrans.Commit();
            }
            catch
            {
                rexTrans.Rollback();
                insightTrans.Rollback();
            }
            finally
            {
                if (rexConn.State != ConnectionState.Closed)
                    rexConn.Close();
                if (insightConn.State != ConnectionState.Closed)
                    insightConn.Close();
            }
        }

        /// <summary>
        /// Serialize Training Certificates
        /// </summary>
        /// <param name="cachePolicy">Prevailing Cache Policy</param>
        /// <param name="questionnaireName">Name of Training Certificate Questionnaire</param>
        /// <returns>Null if no training certificates are available. Otherwise, Forms object</returns>
        public FormsManagement.Serialization.Forms SerializableCertificates(ICachePolicy cachePolicy, string insightConnectionString, string questionnaireName)
        {
            DataTable dt = Utility.DataAccess.GetDataTable(insightConnectionString, "GetCertificationQuestionnaireAnswers",
                        Utility.DataAccess.BuildSqlParameterArray(
                        "@admPersonId", SqlDbType.Int, Id,
                        "@questionnaireName", SqlDbType.VarChar, questionnaireName
                        ));
            if (dt.Rows.Count == 0)
                return null;

            FormsManagement.Serialization.Forms forms = new PHSRAG.Insight21.FormsManagement.Serialization.Forms();
            forms.Today = DateTime.Now.ToString("MMMM dd, yyyy");

            foreach (DataRow dr in dt.Rows)
            {
                QuestionnaireAnswer qA = new QuestionnaireAnswer(cachePolicy, dr);

                QuestionnaireVersion questionnaireVersion = new QuestionnaireVersion(cachePolicy);
                questionnaireVersion.Load(Utility.DataAccess.ConnectionString, (qA.QuestionnaireVersionId));

                forms.FormCollection.Add(questionnaireVersion.GetForm(qA));
            }

            return forms;
        }
		#endregion      
		

		#region Private methods
        private static object GetDBValue(string value)
        {
            return String.IsNullOrEmpty(value) ? (object)DBNull.Value : (object)value;
        }

		/// <summary>
		/// Private method used to populate member variables from a DataRow. This is called from the 
		/// constructor that takes a DataRow, as well as the Load method of an object.
		/// </summary>
		/// <param name="row">row whose data is used to populate instance variables</param>
		private void PopulateDataMembers(DataRow row)
		{
			LastName = (string)row["LastName"];
			FirstName = (string)row["FirstName"];
			object o = row["Username"];
			Username = (o == DBNull.Value) ? string.Empty : (string)o;
			o = row["OrganizationId"];
			OrganizationId = (o == DBNull.Value) ? 0 : (int)o;
			o = row["OrganizationName"];
			OrganizationName = (o == DBNull.Value) ? string.Empty : (string)o;
			AdmPersonType = (int)row["AdmPersonTypeId"];
			o = row["RecomAbstractId"];
			RexRecomId = (o == DBNull.Value) ? 0 : (int)o;

			o = row["UserId"];
			userId = (o == DBNull.Value) ? 0 : (int)o;

			if (row.Table.Columns.Contains("EmailAddress"))
			{
				o = row["EmailAddress"];
				email = (o == DBNull.Value) ? string.Empty : (string)o;
			}
			if (row.Table.Columns.Contains("AreaCode"))
			{
				o = row["Areacode"];
				phoneArea = (o == DBNull.Value) ? string.Empty : (string)o;
			}

			if (row.Table.Columns.Contains("PhoneNumber"))
			{
				o = row["PhoneNumber"];
				phoneNumber = (o == DBNull.Value) ? string.Empty : (string)o;
			}
			if (row.Table.Columns.Contains("FaxArea"))
			{
				o = row["FaxArea"];
				faxArea = (o == DBNull.Value) ? string.Empty : (string)o;
			}
			if (row.Table.Columns.Contains("FaxNumber"))
			{
				o = row["FaxNumber"];
				faxNumber = (o == DBNull.Value) ? string.Empty : (string)o;
			}

		}

		/// <summary>
		/// Determines whether the person's citi certification is up-to-date, and when the person
		/// was certified if at all
		/// </summary>
		private void DetermineCitiData()
		{
			// using an order by to make sure we get the most recent certification date
			DataRow[] citiData = (Certifications.GetDataContainer().Tables[0].Select(
				@"(Type = 'IRB' and Status = 'Pass') OR (Type like 'IRB Cont%' and Subtype like 'CITI%' and 
					Status = 'Pass')", "Date DESC"));

			if (citiData.Length > 0)
			{
				DateTime certDate = (DateTime)citiData[0]["Date"];
				if (certDate == DateTime.MinValue)
					isCitiCertified = false;
				else
				{
					isCitiCertified = (certDate > DateTime.Now.AddYears(-3));
					citiCertDate = certDate.ToString("MM/dd/yyyy");
				}
			}
			else
				isCitiCertified = false;

			citiDataDetermined = true;
		}		
		
		/// <summary>
		/// Determines whether the person's occ health certification is up-to-date, and when the person
		/// was certified if at all
		/// </summary>
		private void DetermineOccHealthData()
		{
			// using an order by to make sure we get the most recent certification date
			DataRow[] occHealthData = (Certifications.GetDataContainer().Tables[0].Select(
				@"(Type = 'IACUC Continuing Education' and Subtype = 'Occupational health program' and 
					Status = 'Pass')", "Date DESC"));

			if (occHealthData.Length > 0)
			{
				DateTime certDate = (DateTime)occHealthData[0]["Date"];
				if (certDate == DateTime.MinValue)
					isOccHealthCertified = false;
				else
				{
					isOccHealthCertified = (certDate > DateTime.Now.AddYears(-3));
					occHealthCertDate = certDate.ToString("MM/dd/yyyy");
				}
			}
			else
				isOccHealthCertified = false;

			occHealthDataDetermined = true;
		}
		#endregion
	}
}